package com.jinglin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jinglin.entity.enums.CommentTopTypeEnum;
import com.jinglin.entity.enums.PageSize;
import com.jinglin.entity.enums.ResponseCodeEnum;
import com.jinglin.entity.enums.UserActionTypeEnum;
import com.jinglin.entity.po.*;
import com.jinglin.entity.query.SimplePage;
import com.jinglin.entity.query.VideoCommentQuery;
import com.jinglin.entity.vo.PaginationResultVO;
import com.jinglin.entity.vo.VideoCommentResultVO;
import com.jinglin.exception.BusinessException;
import com.jinglin.mapper.VideoCommentMapper;
import com.jinglin.mapper.VideoInfoMapper;
import com.jinglin.service.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.search.similarities.Lambda;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 评论 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2025-03-24
 */
@Service
public class VideoCommentServiceImpl extends ServiceImpl<VideoCommentMapper, VideoComment> implements VideoCommentService {
    @Autowired
    private VideoInfoService videoInfoService;
    @Autowired
    private VideoInfoMapper videoInfoMapper;
    @Autowired
    private UserActionService userActionService;
    @Autowired
    private UserInfoService   userInfoService;

    @Autowired
    private VideoCommentMapper videoCommentMapper;

    @Override
    @Transactional
    public VideoComment postComment(VideoComment videoComment,String replyCommentId) {
        VideoInfo videoInfo = videoInfoService.getById(videoComment.getVideoId());
        if (videoInfo == null){
            throw new BusinessException("视频信息不存在！！");
        }
        // 查看是否关闭评论区(有可能用户再评论的同时，up主关闭)
        if (videoInfo.getInteraction()!= null && videoInfo.getInteraction().contains(Constants.ZERO)){
            throw new BusinessException("UP主已关闭评论区");
        }
        // 这条评论是回复别人的评论
        if (replyCommentId != null){
            // 从数据库拿到被回复的评论
            VideoComment replyComment = this.getById(replyCommentId);
            // 如果被回复的评论为null，或者被回复的评论存在，但是不是此条视频的评论
            if (replyComment == null || !replyComment.getVideoId().equals(videoComment.getVideoId())){
                throw new BusinessException(ResponseCodeEnum.CODE_600);
            }
            //设置一个被回复的评论的用户名，方便前端做数据展示
            videoComment.setPCommentId(replyComment.getCommentId());
            videoComment.setPCommentId(replyComment.getCommentId());
            videoComment.setReplyUserId(replyComment.getUserId());
        } else {
            // 如果不是回复别的评论，那么自己就是顶级评论
            videoComment.setPCommentId("0");
        }
        videoComment.setPostTime(LocalDateTime.now());
        videoComment.setVideoUserId(videoInfo.getUserId());
        // 将信息插入
        this.save(videoComment);
        // 增加评论数,我们这里的计划是：只有顶级评论才做评论统计
        if (videoComment.getPCommentId().equals("0")){
            videoInfoMapper.updateCountInfo(UserActionTypeEnum.VIDEO_COMMENT.getField(),1, videoInfo.getVideoId());
        }
        return videoComment;
    }

    @Override
    @Transactional
    public VideoCommentResultVO loadCommentByVideoId(String videoId, Integer pageNo, Integer orderType,String userId) {
        VideoInfo videoInfo = videoInfoService.getById(videoId);
        // 查看是否关闭评论区(有可能用户再评论的同时，up主关闭)
        if (videoInfo.getInteraction()!= null && videoInfo.getInteraction().contains(Constants.ZERO)){
            throw new BusinessException("UP主已关闭评论区");
        }
        LambdaQueryWrapper<VideoComment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(VideoComment::getVideoId,videoId);
        wrapper.eq(VideoComment::getPCommentId,0);
        if (orderType == null ||orderType == 0){
            // 如果orderType == null ||orderType == 0，按照喜欢数和发布时间进行降序
            wrapper.orderByDesc(VideoComment::getLikeCount,VideoComment::getPostTime);
        } else {
            wrapper.orderByDesc(VideoComment::getPostTime);
        }
        if (pageNo == null  || pageNo == 0){
            pageNo = 1;
        }
        LambdaQueryWrapper<VideoComment> commentWrapper = new LambdaQueryWrapper<>();
        commentWrapper.eq(VideoComment::getVideoId,videoId);
        List<VideoComment> allComment = this.list(commentWrapper);
        Page<VideoComment> objectPage = new Page<>(pageNo, PageSize.SIZE15.getSize());
        Page<VideoComment> page = this.page(objectPage, wrapper);
        List<VideoComment> records = page.getRecords();
        // 保存nickName replyNickName……
        setReplyUserInfo(records);

        setReplyUserInfo(allComment);

        setChildren(records, allComment);
        // 置顶排序。首先将所有的非置顶的评论拿出来，再把置顶评论插入到最前面即可。
        List<VideoComment> commentData = records.stream().filter(r -> !r.getTopType().equals(1)).collect(Collectors.toList());
        List<VideoComment> topComments = records.stream().filter(r -> r.getTopType().equals(1)).collect(Collectors.toList());
        commentData.addAll(0,topComments);

        PaginationResultVO<VideoComment> paginationResultVO = new PaginationResultVO<>();
        paginationResultVO.setList(commentData);
        paginationResultVO.setTotalCount((int)page.getTotal());
        paginationResultVO.setPageNo((int)page.getCurrent());
        paginationResultVO.setPageTotal((int)page.getPages());
        paginationResultVO.setPageSize((int)page.getSize());

        // 查找本用户的点赞行为
        List<UserAction> userActionArrayList = new ArrayList<>();
        if (!StringUtils.isEmpty(userId)){
            //如果不为空，或者不为null。则证明本次查询是已登录用户进行的操作
            LambdaQueryWrapper<UserAction> userActionWrapper = new LambdaQueryWrapper<>();
            userActionWrapper.eq(UserAction::getUserId,userId);
            userActionWrapper.eq(UserAction::getVideoId,videoId);
            userActionWrapper.in(UserAction::getActionType, Arrays.asList(UserActionTypeEnum.COMMENT_LIKE.getType(),UserActionTypeEnum.COMMENT_HATE.getType()));
            userActionArrayList = userActionService.list(userActionWrapper);
        }
        VideoCommentResultVO videoCommentResultVO = new VideoCommentResultVO();
        videoCommentResultVO.setCommentData(paginationResultVO);
        videoCommentResultVO.setUserActionList(userActionArrayList);

        return videoCommentResultVO;
    }

    @Override
    public void topComment(String commentId, String userId) {
        VideoComment dbVideoComment = this.getById(commentId);
        LambdaUpdateWrapper<VideoComment> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(VideoComment::getCommentId,commentId);
        wrapper.eq(VideoComment::getVideoId,dbVideoComment.getVideoId());
        wrapper.eq(VideoComment::getTopType,CommentTopTypeEnum.NO_TOP.getType());
        wrapper.set(VideoComment::getTopType,CommentTopTypeEnum.TOP.getType());
        this.update(wrapper);
    }

    @Override
    public void cancelTopComment(String commentId, String userId) {
        //现清除之前的置顶
        VideoComment dbVideoComment = this.getById(commentId);
        if (dbVideoComment == null) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
        VideoInfo videoInfo = videoInfoService.getById(dbVideoComment.getVideoId());
        if (videoInfo == null) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
        if (!videoInfo.getUserId().equals(userId)) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }

        LambdaUpdateWrapper<VideoComment> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(VideoComment::getCommentId,commentId);
        wrapper.eq(VideoComment::getVideoId,dbVideoComment.getVideoId());
        wrapper.eq(VideoComment::getTopType,CommentTopTypeEnum.TOP.getType());
        wrapper.set(VideoComment::getTopType,CommentTopTypeEnum.NO_TOP.getType());
        this.update(wrapper);
    }

    @Override
    public PaginationResultVO loadCommentManage(String videoId,Integer pageNo, Integer pageSize, String userId,String videoNameFuzzy) {
        // 查出当前用户所属视频的所有弹幕数量。
        int count = videoCommentMapper.countWithAllVideo(userId,videoNameFuzzy);
        pageSize = pageSize == null ? PageSize.SIZE15.getSize() : pageSize;

        SimplePage page = new SimplePage(pageNo, count, pageSize);
        List<VideoComment> list = videoCommentMapper.listWithAllVideo(page.getStart(),page.getPageSize(),userId,videoNameFuzzy,videoId);

        PaginationResultVO<UserAction> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);

        return result;
    }

    @Override
    @Transactional
    public void delComment(String commentId, String userId) {
        //减去评论总条数
        VideoComment one = this.getById(commentId);
        // 如果删除的评论是顶级评论，那么评论总数减1
        if (one.getPCommentId().equals("0")){
            String videoId = one.getVideoId();
            LambdaUpdateWrapper<VideoInfo> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(VideoInfo::getVideoId,videoId);
            wrapper.eq(VideoInfo::getUserId,userId);
            wrapper.setSql("comment_count = comment_count - 1");
            videoInfoService.update(wrapper);
        }

        LambdaQueryWrapper<VideoComment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(VideoComment::getCommentId,commentId);
        wrapper.eq(VideoComment::getVideoUserId,userId);
        this.remove(wrapper);
    }


    private void setReplyUserInfo(List<VideoComment> allComment) {
        for (VideoComment record : allComment) {
            String uId = record.getUserId();
            if (!StringUtils.isEmpty(uId)){
                UserInfo user = userInfoService.getById(uId);
                record.setNickName(user.getNickName());
                record.setAvatar(user.getAvatar());
            }
            String replyUserId = record.getReplyUserId();
            if (!StringUtils.isEmpty(replyUserId)){
                UserInfo replyUser = userInfoService.getById(replyUserId);
                record.setReplyNickName(replyUser.getNickName());
                record.setReplyAvatar(replyUser.getAvatar());
            }
        }
    }

    // 设置子评论进去。然后返回
    private List<VideoComment> setChildren(List<VideoComment> videoComments,List<VideoComment> allComment){

        for (VideoComment videoComment : videoComments) {
            List<VideoComment> children = allComment.stream().filter(comment -> comment.getPCommentId().equals(videoComment.getCommentId()))
                    .collect(Collectors.toList());
            if (!children.isEmpty()){
                // 如果子评论不为空，我们在拿子的子评论
                setChildren(children,allComment);
                videoComment.setChildren(children);
            }

        }

        return videoComments;
    }
}
